package com.to.aboomy.banner;

import ohos.aafwk.ability.Ability;
import ohos.agp.components.*;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.global.resource.NotExistException;
import ohos.global.resource.Resource;
import ohos.global.resource.ResourceManager;
import ohos.global.resource.WrongTypeException;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static ohos.aafwk.ability.AbilityLifecycleExecutor.LifecycleState.UNINITIALIZED;
import static ohos.agp.components.ComponentContainer.LayoutConfig.MATCH_PARENT;
import static ohos.multimodalinput.event.TouchEvent.POINT_MOVE;
import static ohos.multimodalinput.event.TouchEvent.PRIMARY_POINT_DOWN;
import static ohos.multimodalinput.event.TouchEvent.PRIMARY_POINT_UP;

/**
 * Banner
 *
 * @since 2021-07-20
 */
public class Banner extends DependentLayout implements PageSlider.PageChangedListener {

    private EventHandler eventHandler = new EventHandler(EventRunner.getMainEventRunner()) {
        @Override
        protected void processEvent(InnerEvent event) {
            super.processEvent(event);
            if (event.eventId == 1 && context != null) {
                System.out.println("==动画");
                if (context instanceof Ability) {
                    Ability ability = (Ability) context;
                    System.out.println("==" + ability.getState());
                    if (ability.getState() == UNINITIALIZED) {
                        stop();
                    }
                }
                InitialValue = viewPager.getCurrentPage() + 1;
                if (InitialValue > views.size() - 1) {
                    InitialValue = 0;
                }
                setCurrentPage(InitialValue);
                long param = 0L;
                Object object = null;
                InnerEvent delayInnerEvent = InnerEvent.get(1, param, object);
                if (eventHandler != null) {
                    eventHandler.sendEvent(delayInnerEvent, autoTurningTime); // 延时2s后立即处理
                }
            }
        }
    };
    private int cornerRadius;
    private int orientation;
    private int magin2 = 0;
    private int padding2 = 60;
    private int InitialValue = 0;
    private static final int DEFAULT_AUTO_TIME = 2500;
    private static final int NORMAL_COUNT = 2;
    private PageSlider.PageChangedListener outerPageChangeListener;
    private OnPageItemClickListener onPageClickListener;
    private HolderCreator holderCreator;

    /**
     * isShwo
     */
    public boolean isShwo = false;
    private BannerViewPager viewPager;
    private List<Integer> views;
    private Indicator indicator;
    private boolean isAutoPlay = true;
    private long autoTurningTime = DEFAULT_AUTO_TIME;
    private boolean isTaskPostDelayed = false;
    List<Component> components;
    private BannerViewPager.PageTransformer mPageTransformer;
    private Context context;
    private int magin = 0;
    private int padding = 0;
    private long Ctime = 0L;

    /**
     * 虚拟当前页 1表示真实页数的第一页
     */
    private int currentPage;
    /**
     * 实际数量
     */
    private int realCount;
    /**
     * 额外的页数是往最左边添加和最右边添加，该变量记录一边添加的数量
     */
    private int sidePage;

    /**
     * 构造函数
     *
     * @param context context
     */
    public Banner(Context context) {
        this(context, null);
    }

    /**
     * 构造函数
     *
     * @param context context
     * @param attrSet attrSet
     */
    public Banner(Context context, AttrSet attrSet) {
        this(context, attrSet, null);

    }

    /**
     * Banner构造函数
     *
     * @param context   context
     * @param attrSet   attrSet
     * @param styleName styleName
     */
    public Banner(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        this.context = context;
        views = new ArrayList<>();
        initViews(context);
    }

    private void initViews(Context context) {
        viewPager = new BannerViewPager(context);
        orientation = Component.HORIZONTAL;
        ComponentContainer.LayoutConfig layoutConfig = new ComponentContainer.LayoutConfig(LayoutConfig.MATCH_PARENT, LayoutConfig.MATCH_PARENT);
        viewPager.setLayoutConfig(layoutConfig);
        viewPager.addPageChangedListener(this);
        addComponent(viewPager);
        viewPager.setIndicationPageSliding(new BannerViewPager.IndicationPageSliding() {
            @Override
            public void onPageSliding(int itemPos, float itemPosOffset, int itemPosOffsetPixels) {
                if (indicator != null) {
                    indicator.onPageSliding(itemPos, itemPosOffset, itemPosOffsetPixels);
                    indicator.setAutoStau(isTaskPostDelayed);
                }
            }

            @Override
            public void onMPageSliding(int itemPos, float itemPosOffset, int itemPosOffsetPixels) {
                if (mBgPageSliding != null) {
                    mBgPageSliding.getOnBgPageSliding(itemPos, itemPosOffset, itemPosOffsetPixels);
                }
            }
        });
        viewPager.setPagerToucheven(toucheven -> {
            if (toucheven.getAction() == PRIMARY_POINT_DOWN) {
                Ctime = System.currentTimeMillis();
            } else if (toucheven.getAction() == POINT_MOVE) {
                stopTurning();

            } else if (toucheven.getAction() == PRIMARY_POINT_UP) {
                if (System.currentTimeMillis() - Ctime < 100) {
                    if (onPageClickListener != null) {
                        onPageClickListener.onPageItemClick(viewPager.getCurrentPage());
                    }
                }
                if (isAutoPlay && realCount > 1) {
                    startTurning();
                }
            }
        });
    }

    /**
     * 页面滑动时调用。
     *
     * @param position            表示显示页面的位置索引
     * @param itemPosOffset       表示页面的位置偏移。取值范围为(0, 1]。0表示正在显示同一个页面；1表示正在显示目标页面。
     * @param itemPosOffsetPixels 表示显示页面的位置偏移像素数。
     */
    @Override
    public void onPageSliding(int position, float itemPosOffset, int itemPosOffsetPixels) {
        if (outerPageChangeListener != null) {
            outerPageChangeListener.onPageSliding(position, itemPosOffset, itemPosOffsetPixels);
        }
    }

    /**
     * 当页面滑动状态改变时调用
     *
     * @param state 指示页面状态。该值可以是 0、1 或 2，分别代表页面处于空闲、拖动或滑动状态。
     */
    @Override
    public void onPageSlideStateChanged(int state) {
        if (indicator != null) {
            indicator.onPageSlideStateChanged(state);
        }
    }

    /**
     * 选择新页面时回调。
     *
     * @param itemPos 指示所选页面的索引。
     */
    @Override
    public void onPageChosen(int itemPos) {
        currentPage = viewPager.getCurrentPage();
        if (outerPageChangeListener != null) {
            outerPageChangeListener.onPageSlideStateChanged(itemPos);
        }
        if (indicator != null) {
            indicator.onPageChosen(itemPos);
        }
    }

    /**
     * 设置banner每张图片容器的间距
     *
     * @param magin   外边距
     * @param padding 内边距
     * @return Banner
     */
    public Banner setPageMargin(int magin, int padding) {
        this.magin = magin;
        this.padding = padding;
        viewPager.setPageCacheSize(2);
        viewPager.setPageMargin(magin, padding);
        viewPager.setCircularModeEnabled(true);
        return this;
    }

    /**
     * 设置轮播图
     *
     * @param imagesUrl List
     * @return List
     * @throws NotExistException
     * @throws WrongTypeException
     * @throws IOException
     */
    private List<Component> setImageList(List<?> imagesUrl) throws NotExistException, WrongTypeException, IOException {
        if (imagesUrl == null || imagesUrl.size() <= 0) {
            return null;
        }
        for (int i = 0; i < imagesUrl.size(); i++) {
            Object url = imagesUrl.get(i);
            Image image1 = new Image(context);
            image1.setScaleMode(Image.ScaleMode.STRETCH);
            image1.setLayoutConfig(new ComponentContainer.LayoutConfig(MATCH_PARENT, MATCH_PARENT));
            if (url instanceof String) {
                Utils2.getInstance().setBitmap(context, image1, (String) url);
            } else {
                ImageSource.SourceOptions options = new ImageSource.SourceOptions();
                options.formatHint = "image/jpg";
                ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
                ResourceManager manager = context.getResourceManager();
                String path = manager.getMediaPath((Integer) url);
                Resource r1 = manager.getRawFileEntry(path).openRawFile();
                ImageSource source = ImageSource.create(r1, options);
                PixelMap p1 = source.createPixelmap(decodingOptions);
                image1.setPixelMap(p1);
            }
            components.add(image1);
        }
        return components;
    }


    /**
     * 重新设置pager
     *
     * @param startPosition 其实位置
     */
    private void startPager(int startPosition) {
        removeComponent(viewPager);
        viewPager = new BannerViewPager(getContext());
        ComponentContainer.LayoutConfig layoutConfig = new ComponentContainer.LayoutConfig(LayoutConfig.MATCH_PARENT, LayoutConfig.MATCH_PARENT);
        viewPager.setLayoutConfig(layoutConfig);
        viewPager.addPageChangedListener(this);
        viewPager.setPageCacheSize(2);
        viewPager.setOrientation(orientation);
        viewPager.setHolderCreator(holderCreator);
        viewPager.setRornerRadius(cornerRadius);
        addComponent(viewPager);
        if (this.indicator != null) {
            moveChildToFront(this.indicator.getView());
        }
        viewPager.setIndicationPageSliding(new BannerViewPager.IndicationPageSliding() {
            @Override
            public void onPageSliding(int itemPos, float itemPosOffset, int itemPosOffsetPixels) {
                if (indicator != null) {
                    indicator.onPageSliding(itemPos, itemPosOffset, itemPosOffsetPixels);
                    indicator.setAutoStau(isTaskPostDelayed);
                }
            }

            @Override
            public void onMPageSliding(int itemPos, float itemPosOffset, int itemPosOffsetPixels) {
                if (mBgPageSliding != null) {
                    mBgPageSliding.getOnBgPageSliding(itemPos, itemPosOffset, itemPosOffsetPixels);
                }
            }
        });
        viewPager.setPagerToucheven(toucheven -> {
            if (toucheven.getAction() == PRIMARY_POINT_DOWN) {
                Ctime = System.currentTimeMillis();
            } else if (toucheven.getAction() == POINT_MOVE) {
                stopTurning();

            } else if (toucheven.getAction() == PRIMARY_POINT_UP) {
                if (System.currentTimeMillis() - Ctime < 100) {
                    if (onPageClickListener != null) {
                        onPageClickListener.onPageItemClick(viewPager.getCurrentPage());
                    }
                }
                if (isAutoPlay && realCount > 1) {
                    startTurning();
                }
            }
        });

        stopTurning();
        if (realCount != 0) {
            viewPager.setHolderCreator(holderCreator);
            viewPager.setPageTransformer(mPageTransformer);
            viewPager.setVisibility(VISIBLE);
            if (realCount == 1) {
//                viewPager.setCurrentPage(0, false);
                viewPager.setPageMargin(magin2, padding2);
                // 禁止滑动
                viewPager.setSlidingPossible(false);
            } else {
                viewPager.setCircularModeEnabled(true);
                viewPager.setPageMargin(magin, padding);
                viewPager.setSlidingPossible(true);
            }
            viewPager.setData(views);
            if (indicator != null) {
                indicator.initIndicatorCount(realCount);
                indicator.getView().invalidate();
            }
            if (isAutoPlay && realCount > 1) {
                startTurning();
            }
        } else {
            viewPager.setVisibility(HIDE);
        }
    }

    /**
     * 初始化集合
     *
     * @param items 图集合
     */
    private void createImages(List<?> items) {
        isShwo = true;
        this.views.clear();
        List<Integer> views2 = new ArrayList<>();
        if (items == null || items.size() == 0) {
            realCount = 0;
            return;
        }
        realCount = items.size();
        for (int i = 0; i < realCount; i++) {
            views2.add((Integer) items.get(i));
        }
        this.views = views2;
    }

    /**
     * 启动轮播
     */
    public void startTurning() {
        InitialValue = viewPager.getCurrentPage();
        stopTurning();
        long param = 0L;
        Object object = null;
        InnerEvent delayInnerEvent = InnerEvent.get(1, param, object);
        eventHandler.sendEvent(delayInnerEvent, autoTurningTime);
        isTaskPostDelayed = true;
    }

    /**
     * 停止轮播
     */
    public void stopTurning() {
        if (isTaskPostDelayed) {
            eventHandler.removeAllEvent();
            isTaskPostDelayed = false;
        }
    }

    /**
     * bannerStop
     */
    public void stop() {
        if (isTaskPostDelayed) {
            System.out.println("==stop");
            eventHandler.removeAllEvent();
            eventHandler = null;
            isTaskPostDelayed = false;
        }
    }

    /**
     * 是否正在轮播
     *
     * @return boolean
     */
    public boolean isAutoPlay() {
        return isAutoPlay && realCount > 1;
    }

    /**
     * 设置动画
     *
     * @param reverseDrawingOrder reverseDrawingOrder
     * @param transformer         transformer
     * @return Banner
     */
    public Banner setPageTransformer(boolean reverseDrawingOrder, BannerViewPager.PageTransformer transformer) {
        if (viewPager != null) {
            viewPager.setPageTransformer(transformer);
        }
        this.mPageTransformer = transformer;
        return this;
    }

    /**
     * setAutoTurningTime
     *
     * @param autoTurningTime int
     * @return Banner
     */
    public Banner setAutoTurningTime(int autoTurningTime) {
        this.autoTurningTime = autoTurningTime;
        return this;
    }

    /**
     * setOuterPageChangeListener
     *
     * @param outerPageChangeListener PageSlider.PageChangedListener
     * @return Banner
     */
    public Banner setOuterPageChangeListener(PageSlider.PageChangedListener outerPageChangeListener) {
        this.outerPageChangeListener = outerPageChangeListener;
        return this;
    }

    /**
     * 设置viewpager的切换时长
     *
     * @param pagerScrollDuration int
     * @return Banner
     */
    public Banner setPagerScrollDuration(int pagerScrollDuration) {
        viewPager.setPageSwitchTime(pagerScrollDuration);
        return this;
    }

    /**
     * 是否自动轮播 大于1页轮播才生效
     *
     * @param autoPlay autoPlay
     * @return Banner
     */
    public Banner setAutoPlay(boolean autoPlay) {
        isAutoPlay = autoPlay;
        if (isAutoPlay && realCount > 1) {
            startTurning();
        } else {
            stopTurning();
        }
        return this;
    }

    /**
     * setIndicator
     *
     * @param indicator Indicator
     * @return Banner
     */
    public Banner setIndicator(Indicator indicator) {
        return setIndicator(indicator, true);
    }

    /**
     * 设置indicator，支持在xml中创建
     *
     * @param indicator    Indicator
     * @param attachToRoot true 添加到banner布局中
     * @return Banner
     */
    public Banner setIndicator(Indicator indicator, boolean attachToRoot) {
        if (this.indicator != null) {
            removeComponent(this.indicator.getView());
        }
        if (indicator != null) {
            this.indicator = indicator;
            if (attachToRoot) {
                addComponent(this.indicator.getView(), this.indicator.getParams());
            }
        }
        return this;
    }

    /**
     * setOnPageClickListener
     *
     * @param onPageClickListener OnPageItemClickListener
     * @return Banner
     */
    public Banner setOnPageClickListener(OnPageItemClickListener onPageClickListener) {
        this.onPageClickListener = onPageClickListener;
        return this;
    }

    /**
     * setPages
     *
     * @param items         数据集
     * @param startPosition 开始位置 真实索引
     */
    public void setPages(List<?> items, int startPosition) {
        createImages(items);
        startPager(startPosition);
    }

    /**
     * 设置数据集
     *
     * @param items items
     */
    public void setPages(List<?> items) {
        setPages(items, 0);
    }

    /**
     * 返回真实位置
     *
     * @return int
     */
    public int getCurrentPager() {
        return currentPage;
    }

    /**
     * 设置圆角
     *
     * @param cornerRadius int
     * @return Banner
     */
    public Banner setCornerRadius(int cornerRadius) {
        this.cornerRadius = cornerRadius;
        viewPager.setRornerRadius(cornerRadius);
        return this;
    }

    /**
     * 回调onPageSliding 函数
     */

    public BgPageSliding mBgPageSliding;

    /**
     * 设置图片加载器
     *
     * @param holderCreator 图片加载器
     * @return Banner
     */
    public Banner setHolderCreator(HolderCreator holderCreator) {
        this.holderCreator = holderCreator;
        return this;
    }

    /**
     * 设置只有一页的时候的编剧
     *
     * @param magin2   magin
     * @param padding2 padding
     * @return Banner
     */
    public Banner setPageMargin2(int magin2, int padding2) {
        this.padding2 = padding2;
        this.magin2 = magin2;
        return this;
    }

    /**
     * 转转监听接口
     *
     * @since 2021-07-16
     */
    public interface BgPageSliding {
        /**
         * 滑动监听
         *
         * @param itemPos             itemPos
         * @param itemPosOffset       itemPosOffset
         * @param itemPosOffsetPixels itemPosOffsetPixels
         */
        void getOnBgPageSliding(int itemPos, float itemPosOffset, int itemPosOffsetPixels);
    }

    /**
     * 设置第几页
     *
     * @param page int
     */
    public void setCurrentPage(int page) {
        viewPager.setCurrentPage(page, true);
    }

    /**
     * 设置自动播放时间
     *
     * @param autoTurningTime long
     * @return Banner
     */
    public Banner setAutoTurningTime(long autoTurningTime) {
        this.autoTurningTime = autoTurningTime;
        return this;
    }

    /**
     * 设置banner方向
     *
     * @param orientation Component.VERTICAL
     * @return Banner
     */
    public Banner setOrientation(int orientation) {
        this.orientation = orientation;
        return this;
    }
}
